-- SPDX-License-Identifier: GPL-3.0-or-later

local VslUtil = {}

--狂野模式开关
--记得把zzsystem.lua里的也设置为true
-- VslUtil.wild_mode = false --狂野模式！！（仅限服务器用，解放偷梁换柱、猴子）

--------------------------------------------------
--combobox大全
--------------------------------------------------

VslUtil.basic = {
  "slash", "peach", "analeptic",
  "fire__slash", "thunder__slash", "v_ice__slash"
}
VslUtil.normal_tricks = {
  "dismantlement", "snatch", "duel", "collateral",
  "ex_nihilo", "savage_assault", "archery_attack", "god_salvation",
  "amazing_grace", "iron_chain", "fire_attack",
}
VslUtil.not_damage_tricks = {
  "dismantlement", "snatch", "collateral",
  "ex_nihilo", "god_salvation",
  "amazing_grace", "iron_chain",
}
VslUtil.damage_tricks = {
  "duel", "fire_attack", "savage_assault", "archery_attack",
}
VslUtil.suits = {
   "heart", "diamond", "spade", "club",
}

--------------------------------------------------
--标签显示大全
--------------------------------------------------

VslUtil.short_card_type = {
  basic = "基",
  trick = "锦",
  equip = "装",
}

VslUtil.card_suits_table = {
  spade = "♠",
  club = "♣",
  heart = "♥",
  diamond = "♦",
}

--------------------------------------------------
--三目运算符
--------------------------------------------------

VslUtil.Ternary = function(A, B, C)
	if A then
		return B
	else
		return C
	end
end

--- 更换牌所处区域的描述
---@param card_position integer
---@return integer
VslUtil.cpos_change = function(card_position)
  local car = Card.Unknown
  if card_position == Player.Hand then
    car = Card.PlayerHand
  elseif card_position == Player.Equip then
    car = Card.PlayerEquip
  elseif card_position == Player.Judge then
    car = Card.PlayerJudge
  end
  return car
end

--- 交换两个角色的同区域手牌
---@param target1 ServerPlayer
---@param target2 ServerPlayer
---@param card_position integer
---@param skillname string
VslUtil.exchange_cards = function(target1, target2, card_position, skillname)
  if target1:isAlive() and target2:isAlive() then
    local room = target1.room
    local cards1 = table.clone(target1.player_cards[card_position])
    local cards2 = table.clone(target2.player_cards[card_position])
    local moveInfos = {}
    if #cards1 > 0 then
      table.insert(moveInfos, {
        from = target1.id,
        ids = cards1,
        toArea = Card.Processing,
        moveReason = fk.ReasonExchange,
        skillName = skillname,
      })
    end
    if #cards2 > 0 then
      table.insert(moveInfos, {
        from = target2.id,
        ids = cards2,
        toArea = Card.Processing,
        moveReason = fk.ReasonExchange,
        skillName = skillname,
      })
    end
    if #moveInfos > 0 then
      room:moveCards(table.unpack(moveInfos))
    end
    moveInfos = {}
    if not target2.dead then
      local to_ex_cards = table.filter(cards1, function (id)
        return room:getCardArea(id) == Card.Processing
      end)
      if #to_ex_cards > 0 then
        table.insert(moveInfos, {
          ids = to_ex_cards,
          fromArea = Card.Processing,
          to = target2.id,
          toArea = VslUtil.cpos_change(card_position),
          moveReason = fk.ReasonExchange,
          skillName = skillname,
        })
      end
    end
    if not target1.dead then
      local to_ex_cards = table.filter(cards2, function (id)
        return room:getCardArea(id) == Card.Processing
      end)
      if #to_ex_cards > 0 then
        table.insert(moveInfos, {
          ids = to_ex_cards,
          fromArea = Card.Processing,
          to = target1.id,
          toArea = VslUtil.cpos_change(card_position),
          moveReason = fk.ReasonExchange,
          skillName = skillname,
        })
      end
    end
    if #moveInfos > 0 then
      room:moveCards(table.unpack(moveInfos))
    end
    table.insertTable(cards1, cards2)
    local dis_cards = table.filter(cards1, function (id)
      return room:getCardArea(id) == Card.Processing
    end)
    if #dis_cards > 0 then
      local dummy = Fk:cloneCard("dilu")
      dummy:addSubcards(dis_cards)
      room:moveCardTo(dummy, Card.DiscardPile, nil, fk.ReasonPutIntoDiscardPile, skillname)
    end
  end
end

--- 附身式换角色状态
---@param player ServerPlayer
---@param player2 ServerPlayer
VslUtil.swap_player = function(player, player2, skillname)
  local room = player.room
  VslUtil.exchange_cards(player, player2, Player.Hand, skillname)
  VslUtil.exchange_cards(player, player2, Player.Equip, skillname)
  VslUtil.exchange_cards(player, player2, Player.Judge, skillname)
  if player:isAlive() and player2:isAlive() then
    room:swapSeat(player, player2)
  end
end

--- 检查玩家是否存在对应阶段
---@param player ServerPlayer
---@param Phase integer
---@return boolean
VslUtil.exist_or_not = function(player, Phase)
    local exist_truth = true
    if player.skipped_phases ~= {} then
        for k in ipairs(player.skipped_phases) do
        if k == Phase then
            exist_truth = false
        end
        end
    end
    return exist_truth
end

--- 检查是否不能使用、打出或弃置某种牌
---@param player ServerPlayer
---@param card Card
---@return boolean
VslUtil.is_jilei = function(player, card)
    local is_jilei_or_not = false
    -- if not player:canUse(card) or player:prohibitUse(card) or player:prohibitDiscard(card) or player:prohibitResponse(card) then
    if player:prohibitUse(card) or player:prohibitDiscard(card) or player:prohibitResponse(card) then
        is_jilei_or_not = true
    end
    return is_jilei_or_not
end


--- 返回牌堆
---@param player ServerPlayer
---@param cards integer[]
---@param skillName string
VslUtil.return_draw_pile = function(player, cards, skillName)
    local room = player.room
    local ram = math.random(1, #room.draw_pile + 1)
    room:moveCards({
        ids = cards,
        from = player.id,
        toArea = Card.DrawPile,
        moveReason = fk.ReasonJustMove,
        skillName = skillName,
        drawPilePosition = ram,
    })
end

--- 判断花色相近
---@param suit Suit
---@return Suit
VslUtil.suit_close = function(suit)
    if suit == Card.Spade then
        return Card.Club
    elseif suit == Card.Club then
        return Card.Spade
    elseif suit == Card.Heart then
        return Card.Diamond
    elseif suit == Card.Diamond then
        return Card.Heart
    end
    return Card.NoSuit
end
  
--- 判断花色相对
---@param suit Suit
---@return Suit
VslUtil.suit_opposite = function(suit)
    if suit == Card.Spade then
        return Card.Heart
    elseif suit == Card.Club then
        return Card.Diamond
    elseif suit == Card.Heart then
        return Card.Spade
    elseif suit == Card.Diamond then
        return Card.Club
    end
    return Card.NoSuit
end

--- 返回花色数字对应的字段
---@param suit Suit
---@return string
VslUtil.suit_string = function(suit)
    if suit == Card.Club then
        return "club"
    elseif suit == Card.Spade then
        return "spade"
    elseif suit == Card.Diamond then
        return "diamond"
    elseif suit == Card.Heart then
        return "heart"
    end
    return "unknown"
end
  
--------------------------------------------------
--返回花色字段对应的数字
--------------------------------------------------

--- 返回花色数字对应的字段
---@param s string
---@return Suit
VslUtil.suit_number = function(s)
  if s == "club" then
    return Card.Club
  elseif s == "spade" then
    return Card.Spade
  elseif s == "diamond" then
    return Card.Diamond
  elseif s == "heart" then
    return Card.Heart
  end
end

---返回phase对应的字符串
---请注意8 notactive、9 phasenone暂无官方叫法，暂未写入
---@param phase_int integer
---@return string
VslUtil.phase_string = function(phase_int)
  if phase_int == 1 then
    return "回合开始"
  elseif phase_int == 2 then
    return "准备"
  elseif phase_int == 3 then
    return "判定"
  elseif phase_int == 4 then
    return "摸牌"
  elseif phase_int == 5 then
    return "出牌"
  elseif phase_int == 6 then
    return "弃牌"
  elseif phase_int == 7 then
    return "结束"
  elseif phase_int == 8 then
    return "回合外"
  elseif phase_int == 9 then
    return "空白"
  end
  return "未知"
end

---交互方式逃课方案1
---@param player ServerPlayer
---@param skill_name string
---@param prompt string|nil @ 提示信息
---@return boolean
VslUtil.yes_or_no = function(player, skill_name, prompt)
  local room = player.room
  local choiceList = {}
  table.insert(choiceList, "confirm")
  table.insert(choiceList, "cancel")
  local choice = room:askForChoice(player, choiceList, skill_name, prompt)
  if choice == "confirm" then
    return true
  end
  return false
end

return VslUtil